home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xpuzzles.3 / xpuzzles / xpuzzles-5.3.1 / xdino / Dino3d.c < prev    next >
C/C++ Source or Header  |  1996-04-02  |  36KB  |  1,073 lines

  1. /*
  2. # X-BASED DINOSAUR CUBE
  3. #
  4. #  Dino3d.c
  5. #
  6. ###
  7. #
  8. #  Copyright (c) 1995 - 96    David Albert Bagley, bagleyd@hertz.njit.edu
  9. #
  10. #                   All Rights Reserved
  11. #
  12. #  Permission to use, copy, modify, and distribute this software and
  13. #  its documentation for any purpose and without fee is hereby granted,
  14. #  provided that the above copyright notice appear in all copies and
  15. #  that both that copyright notice and this permission notice appear in
  16. #  supporting documentation, and that the name of the author not be
  17. #  used in advertising or publicity pertaining to distribution of the
  18. #  software without specific, written prior permission.
  19. #
  20. #  This program is distributed in the hope that it will be "playable",
  21. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  23. #
  24. */
  25.  
  26. /* Methods file for Dino3d */
  27.  
  28. #include <stdio.h>
  29. #include <X11/IntrinsicP.h>
  30. #include <X11/Intrinsic.h>
  31. #include <X11/StringDefs.h>
  32. #include <X11/CoreP.h>
  33. #include "DinoP.h"
  34. #include "Dino3dP.h"
  35.  
  36. static void InitializeDino3D();
  37. static void ExposeDino3D();
  38. static void ResizeDino3D();
  39. static Boolean SetValuesDino3D();
  40. static void MoveDino3DCcw();
  41. static void MoveDino3DTl();
  42. static void MoveDino3DTop();
  43. static void MoveDino3DTr();
  44. static void MoveDino3DLeft();
  45. static void MoveDino3DCw();
  46. static void MoveDino3DRight();
  47. static void MoveDino3DBl();
  48. static void MoveDino3DBottom();
  49. static void MoveDino3DBr();
  50. static void ResizePolyhedrons();
  51. static void DrawFrame();
  52. static void DiamondOffset3D();
  53. static void MapFrom3D();
  54. static void MapTo3D();
  55. static void CubeOffset3D();
  56.  
  57. static char defaultTranslationsDino3D[] =
  58.   "<KeyPress>q: Quit()\n\
  59.    Ctrl<KeyPress>C: Quit()\n\
  60.    <KeyPress>KP_Divide: MoveCcw()\n\
  61.    <KeyPress>Home: MoveTl()\n\
  62.    <KeyPress>KP_7: MoveTl()\n\
  63.    <KeyPress>R7: MoveTl()\n\
  64.    <KeyPress>Up: MoveTop()\n\
  65.    <KeyPress>KP_8: MoveTop()\n\
  66.    <KeyPress>R8: MoveTop()\n\
  67.    <KeyPress>Prior: MoveTr()\n\
  68.    <KeyPress>KP_9: MoveTr()\n\
  69.    <KeyPress>R9: MoveTr()\n\
  70.    <KeyPress>Left: MoveLeft()\n\
  71.    <KeyPress>KP_4: MoveLeft()\n\
  72.    <KeyPress>R10: MoveLeft()\n\
  73.    <KeyPress>Begin: MoveCw()\n\
  74.    <KeyPress>KP_5: MoveCw()\n\
  75.    <KeyPress>R11: MoveCw()\n\
  76.    <KeyPress>Right: MoveRight()\n\
  77.    <KeyPress>KP_6: MoveRight()\n\
  78.    <KeyPress>R12: MoveRight()\n\
  79.    <KeyPress>End: MoveBl()\n\
  80.    <KeyPress>KP_1: MoveBl()\n\
  81.    <KeyPress>R13: MoveBl()\n\
  82.    <KeyPress>Down: MoveBottom()\n\
  83.    <KeyPress>KP_2: MoveBottom()\n\
  84.    <KeyPress>R14: MoveBottom()\n\
  85.    <KeyPress>Next: MoveBr()\n\
  86.    <KeyPress>KP_3: MoveBr()\n\
  87.    <KeyPress>R15: MoveBr()\n\
  88.    <Btn1Down>: Select()\n\
  89.    <Btn1Up>: Release()\n\
  90.    <KeyPress>p: Practice()\n\
  91.    <Btn2Down>(2+): Practice()\n\
  92.    <Btn2Down>: PracticeMaybe()\n\
  93.    <KeyPress>r: Randomize()\n\
  94.    <Btn3Down>(2+): Randomize()\n\
  95.    <Btn3Down>: RandomizeMaybe()\n\
  96.    <KeyPress>g: Get()\n\
  97.    <KeyPress>w: Write()\n\
  98.    <KeyPress>u: Undo()\n\
  99.    <KeyPress>s: Solve()\n\
  100.    <KeyPress>o: Orientize()\n\
  101.    <KeyPress>2: Period2()\n\
  102.    <KeyPress>3: Period3()\n\
  103.    <KeyPress>b: Both()";
  104.  
  105. static XtActionsRec actionsListDino3D[] =
  106. {
  107.   {"Quit", (XtActionProc) QuitDino},
  108.   {"MoveCcw", (XtActionProc) MoveDino3DCcw},
  109.   {"MoveTl", (XtActionProc) MoveDino3DTl},
  110.   {"MoveTop", (XtActionProc) MoveDino3DTop},
  111.   {"MoveTr", (XtActionProc) MoveDino3DTr},
  112.   {"MoveLeft", (XtActionProc) MoveDino3DLeft},
  113.   {"MoveCw", (XtActionProc) MoveDino3DCw},
  114.   {"MoveRight", (XtActionProc) MoveDino3DRight},
  115.   {"MoveBl", (XtActionProc) MoveDino3DBl},
  116.   {"MoveBottom", (XtActionProc) MoveDino3DBottom},
  117.   {"MoveBr", (XtActionProc) MoveDino3DBr},
  118.   {"Select", (XtActionProc) SelectDino},
  119.   {"Release", (XtActionProc) ReleaseDino},
  120.   {"Practice", (XtActionProc) PracticeDino},
  121.   {"PracticeMaybe", (XtActionProc) PracticeDinoMaybe},
  122.   {"Randomize", (XtActionProc) RandomizeDino},
  123.   {"RandomizeMaybe", (XtActionProc) RandomizeDinoMaybe},
  124.   {"Get", (XtActionProc) GetDino},
  125.   {"Write", (XtActionProc) WriteDino},
  126.   {"Undo", (XtActionProc) UndoDino},
  127.   {"Solve", (XtActionProc) SolveDino},
  128.   {"Orientize", (XtActionProc) OrientizeDino},
  129.   {"Period2", (XtActionProc) Period2ModeDino},
  130.   {"Period3", (XtActionProc) Period3ModeDino},
  131.   {"Both", (XtActionProc) BothModeDino}
  132. };
  133.  
  134. static XtResource resourcesDino3D[] =
  135. {
  136.   {XtNfaceColor0, XtCLabel, XtRString, sizeof(String),
  137.    XtOffset(DinoWidget, dino.faceName[0]), XtRString, "Orange"},
  138.   {XtNfaceColor1, XtCLabel, XtRString, sizeof(String),
  139.    XtOffset(DinoWidget, dino.faceName[1]), XtRString, "Pink"},
  140.   {XtNfaceColor2, XtCLabel, XtRString, sizeof(String),
  141.    XtOffset(DinoWidget, dino.faceName[2]), XtRString, "White"},
  142.   {XtNfaceColor3, XtCLabel, XtRString, sizeof(String),
  143.    XtOffset(DinoWidget, dino.faceName[3]), XtRString, "Violet"},
  144.   {XtNfaceColor4, XtCLabel, XtRString, sizeof(String),
  145.    XtOffset(DinoWidget, dino.faceName[4]), XtRString, "Yellow"},
  146.   {XtNfaceColor5, XtCLabel, XtRString, sizeof(String),
  147.    XtOffset(DinoWidget, dino.faceName[5]), XtRString, "Blue"},
  148.   {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  149.    XtOffset(DinoWidget, dino.foreground), XtRString, XtDefaultForeground},
  150.   {XtNpieceBorder, XtCColor, XtRPixel, sizeof(Pixel),
  151.    XtOffset(DinoWidget, dino.borderColor), XtRString, XtDefaultForeground},
  152.   {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
  153.    XtOffset(DinoWidget, core.width), XtRString, "250"},
  154.   {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
  155.    XtOffset(DinoWidget, core.height), XtRString, "400"},
  156.   {XtNmode, XtCMode, XtRInt, sizeof(int),
  157.    XtOffset(DinoWidget, dino.mode), XtRString, "3"}, /*DEFAULTMODE*/
  158.   {XtNorient, XtCOrient, XtRBoolean, sizeof(Boolean),
  159.    XtOffset(DinoWidget, dino.orient), XtRString, "FALSE"}, /* DEFAULTORIENT */
  160.   {XtNmono, XtCMono, XtRBoolean, sizeof(Boolean),
  161.    XtOffset(DinoWidget, dino.mono), XtRString, "FALSE"},
  162.   {XtNface, XtCFace, XtRInt, sizeof(int),
  163.    XtOffset(DinoWidget, dino.currentFace), XtRString, "-1"},
  164.   {XtNpos, XtCPos, XtRInt, sizeof(int),
  165.    XtOffset(DinoWidget, dino.currentPosition), XtRString, "-1"},
  166.   {XtNdirection, XtCDirection, XtRInt, sizeof(int),
  167.    XtOffset(DinoWidget, dino.currentDirection), XtRString, "-1"},
  168.   {XtNstyle, XtCStyle, XtRInt, sizeof(int),
  169.    XtOffset(DinoWidget, dino.style), XtRString, "-1"},
  170.   {XtNpractice, XtCBoolean, XtRBoolean, sizeof(Boolean),
  171.    XtOffset(DinoWidget, dino.practice), XtRString, "FALSE"},
  172.   {XtNstart, XtCBoolean, XtRBoolean, sizeof(Boolean),
  173.    XtOffset(DinoWidget, dino.started), XtRString, "FALSE"},
  174.   {XtNselectCallback, XtCCallback, XtRCallback, sizeof(caddr_t),
  175.    XtOffset(DinoWidget, dino.select), XtRCallback, NULL}
  176. };
  177.  
  178. Dino3DClassRec dino3dClassRec =
  179. {
  180.   {
  181.     (WidgetClass) &dinoClassRec,    /* superclass */
  182.     "Dino3D",                /* class name */
  183.     sizeof(Dino3DRec),            /* widget size */
  184.     NULL,                /* class initialize */
  185.     NULL,                /* class part initialize */
  186.     FALSE,                /* class inited */
  187.     InitializeDino3D,            /* initialize */
  188.     NULL,                /* initialize hook */
  189.     XtInheritRealize,            /* realize */
  190.     actionsListDino3D,            /* actions */
  191.     XtNumber(actionsListDino3D),    /* num actions */
  192.     resourcesDino3D,            /* resources */
  193.     XtNumber(resourcesDino3D),        /* num resources */
  194.     NULLQUARK,                /* xrm class */
  195.     TRUE,                /* compress motion */
  196.     TRUE,                /* compress exposure */
  197.     TRUE,                /* compress enterleave */
  198.     TRUE,                /* visible interest */
  199.     NULL,                /* destroy */
  200.     ResizeDino3D,            /* resize */
  201.     ExposeDino3D,            /* expose */
  202.     SetValuesDino3D,            /* set values */
  203.     NULL,                /* set values hook */
  204.     XtInheritSetValuesAlmost,        /* set values almost */
  205.     NULL,                /* get values hook */
  206.     XtInheritAcceptFocus,        /* accept focus */
  207.     XtVersion,                /* version */
  208.     NULL,                /* callback private */
  209.     defaultTranslationsDino3D,        /* tm table */
  210.     NULL,                /* query geometry */
  211.     NULL,                /* display accelerator */
  212.     NULL                /* extension */
  213.   },
  214.   {
  215.     0                    /* ignore */
  216.   },
  217.   {
  218.     0                    /* ignore */
  219.   }
  220. };
  221.  
  222. WidgetClass dino3dWidgetClass = (WidgetClass) &dino3dClassRec;
  223.  
  224. static XPoint faceLoc3D[MAXFACES][MAXORIENT];
  225. static XPoint cubeLoc3D[MAXFACES][MAXORIENT];
  226. static XPoint diamondLoc3D[MAXFACES][MAXORIENT];
  227. static XPoint tinyDiamondLoc3D[MAXFACES][MAXORIENT];
  228. static XPoint triangleLoc3D[MAXFACES][MAXORIENT][4];
  229. static XPoint letter3DList[MAXFACES][MAXORIENT];
  230. static XPoint orientTriangle[MAXFACES][MAXORIENT][2];
  231.  
  232. static void InitializeDino3D(request, new)
  233.   Widget request, new;
  234. {
  235.   Dino3DWidget w = (Dino3DWidget) new;
  236.  
  237.   w->dino.dim = 3;
  238.   ResizeDino3D(w);
  239. }
  240.  
  241. static void ResizeDino3D(w)
  242.   Dino3DWidget w;
  243. {
  244.   XPoint tempSize;
  245.  
  246.   w->dino.delta = 4;
  247.   w->dino.vertical = (w->core.height >= w->core.width);
  248.   if (w->dino.vertical) {
  249.     tempSize.y = w->core.height / MAXVIEWS;
  250.     tempSize.x = w->core.width;
  251.     if (tempSize.x >= DIVIDE(tempSize.y))
  252.     {
  253.       w->dino3d.cubeSize.y = MAX((tempSize.y - 3 * w->dino.delta) / 2 -
  254.         w->dino.delta - 2, 0);
  255.       w->dino3d.cubeSize.x = DIVIDE(w->dino3d.cubeSize.y);
  256.     } else {
  257.       w->dino3d.cubeSize.x = MAX((tempSize.x - 2 * w->dino.delta - 7) / 2 -
  258.         w->dino.delta, 0);
  259.       w->dino3d.cubeSize.y = MULTIPLY(w->dino3d.cubeSize.x);
  260.     }
  261.     w->dino3d.cubeDiagonal = w->dino3d.cubeSize.x / 2;
  262.     w->dino3d.faceSize.x = w->dino3d.cubeSize.x + 2 * w->dino.delta + 1;
  263.     w->dino3d.faceSize.y = w->dino3d.cubeSize.y + 2 * w->dino.delta + 1;
  264.     w->dino3d.faceDiagonal = w->dino3d.faceSize.x / 2;
  265.     w->dino3d.viewSize.x = 2 * w->dino3d.faceSize.x + 3;
  266.     w->dino3d.viewSize.y = 2 * w->dino3d.faceSize.y + 3;
  267.     w->dino.puzzleSize.x = w->dino3d.viewSize.x + 1;
  268.     w->dino.puzzleSize.y = MAXVIEWS * w->dino3d.viewSize.y + 1;
  269.   } else {
  270.     tempSize.x = w->core.width / MAXVIEWS;
  271.     tempSize.y = w->core.height;
  272.     if (tempSize.y >= DIVIDE(tempSize.x)) {
  273.       w->dino3d.cubeSize.x = MAX((tempSize.x - 3 * w->dino.delta) / 2 -
  274.         w->dino.delta - 2, 0);
  275.       w->dino3d.cubeSize.y = DIVIDE(w->dino3d.cubeSize.x);
  276.     } else {
  277.       w->dino3d.cubeSize.y = MAX((tempSize.y - 2 * w->dino.delta - 7) / 2 -
  278.         w->dino.delta, 0);
  279.       w->dino3d.cubeSize.x = MULTIPLY(w->dino3d.cubeSize.y);
  280.     }
  281.     w->dino3d.cubeDiagonal = w->dino3d.cubeSize.y / 2;
  282.     w->dino3d.faceSize.y = w->dino3d.cubeSize.y + 2 * w->dino.delta + 1;
  283.     w->dino3d.faceSize.x = w->dino3d.cubeSize.x + 2 * w->dino.delta + 1;
  284.     w->dino3d.faceDiagonal = w->dino3d.faceSize.y / 2;
  285.     w->dino3d.viewSize.y = 2 * w->dino3d.faceSize.y + 3;
  286.     w->dino3d.viewSize.x = 2 * w->dino3d.faceSize.x + 3;
  287.     w->dino.puzzleSize.y = w->dino3d.viewSize.y + 1;
  288.     w->dino.puzzleSize.x = MAXVIEWS * w->dino3d.viewSize.x + 1;
  289.   }
  290.   w->dino.puzzleOffset.x = ((int) w->core.width - w->dino.puzzleSize.x) / 2;
  291.   w->dino.puzzleOffset.y = ((int) w->core.height - w->dino.puzzleSize.y) /
  292.     2;
  293.   ResizePolyhedrons(w);
  294. }
  295.  
  296. static void ExposeDino3D(new, event, region)
  297.   Widget new;
  298.   XEvent *event;
  299.   Region region; /* Not used */
  300. {
  301.   Dino3DWidget w = (Dino3DWidget) new;
  302.  
  303.   if (w->core.visible) {
  304.     DrawFrame(w, w->dino.puzzleGC);
  305.     DrawAllPolyhedrons((DinoWidget) w);
  306.   }
  307. }
  308.  
  309. static Boolean SetValuesDino3D(current, request, new)
  310.   Widget current, request, new;
  311. {
  312.   Dino3DWidget c = (Dino3DWidget) current, w = (Dino3DWidget) new;
  313.   Boolean redraw = FALSE;
  314.  
  315.   if (w->dino3d.cubeSize.x != c->dino3d.cubeSize.x) {
  316.     ResizeDino3D(w);
  317.     redraw = TRUE;
  318.   }
  319.   return (redraw);
  320. }
  321.  
  322. static void MoveDino3DTl(w, event, args, nArgs)
  323.   Dino3DWidget w;
  324.   XEvent *event;
  325.   char *args[];
  326.   int nArgs;
  327. {
  328.   MoveDinoInput((DinoWidget) w, event->xbutton.x, event->xbutton.y, TL,
  329.     (int) (event->xkey.state & (ShiftMask | LockMask)),
  330.     (int) (event->xkey.state & ControlMask),
  331.     (int) (event->xkey.state &
  332.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)));
  333. }
  334.  
  335. static void MoveDino3DTop(w, event, args, nArgs)
  336.   Dino3DWidget w;
  337.   XEvent *event;
  338.   char *args[];
  339.   int nArgs;
  340. {
  341.   MoveDinoInput((DinoWidget) w, event->xbutton.x, event->xbutton.y, TOP,
  342.     (int) (event->xkey.state & (ShiftMask | LockMask)),
  343.     (int) (event->xkey.state & ControlMask),
  344.     (int) (event->xkey.state &
  345.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)));
  346. }
  347.  
  348. static void MoveDino3DTr(w, event, args, nArgs)
  349.   Dino3DWidget w;
  350.   XEvent *event;
  351.   char *args[];
  352.   int nArgs;
  353. {
  354.   MoveDinoInput((DinoWidget) w, event->xbutton.x, event->xbutton.y, TR,
  355.     (int) (event->xkey.state & (ShiftMask | LockMask)),
  356.     (int) (event->xkey.state & ControlMask),
  357.     (int) (event->xkey.state &
  358.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)));
  359. }
  360.  
  361. static void MoveDino3DLeft(w, event, args, nArgs)
  362.   Dino3DWidget w;
  363.   XEvent *event;
  364.   char *args[];
  365.   int nArgs;
  366. {
  367.   MoveDinoInput((DinoWidget) w, event->xbutton.x, event->xbutton.y, LEFT,
  368.     (int) (event->xkey.state & (ShiftMask | LockMask)),
  369.     (int) (event->xkey.state & ControlMask),
  370.     (int) (event->xkey.state &
  371.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)));
  372. }
  373.  
  374. static void MoveDino3DCw(w, event, args, nArgs)
  375.   Dino3DWidget w;
  376.   XEvent *event;
  377.   char *args[];
  378.   int nArgs;
  379. {
  380.   MoveDinoInput((DinoWidget) w, event->xbutton.x, event->xbutton.y, CW,
  381.     (int) (event->xkey.state & (ShiftMask | LockMask)),
  382.     (int) (event->xkey.state & ControlMask),
  383.     (int) (event->xkey.state &
  384.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)));
  385. }
  386.  
  387. static void MoveDino3DRight(w, event, args, nArgs)
  388.   Dino3DWidget w;
  389.   XEvent *event;
  390.   char *args[];
  391.   int nArgs;
  392. {
  393.   MoveDinoInput((DinoWidget) w, event->xbutton.x, event->xbutton.y, RIGHT,
  394.     (int) (event->xkey.state & (ShiftMask | LockMask)),
  395.     (int) (event->xkey.state & ControlMask),
  396.     (int) (event->xkey.state &
  397.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)));
  398. }
  399.  
  400. static void MoveDino3DBl(w, event, args, nArgs)
  401.   Dino3DWidget w;
  402.   XEvent *event;
  403.   char *args[];
  404.   int nArgs;
  405. {
  406.   MoveDinoInput((DinoWidget) w, event->xbutton.x, event->xbutton.y, BL,
  407.     (int) (event->xkey.state & (ShiftMask | LockMask)),
  408.     (int) (event->xkey.state & ControlMask),
  409.     (int) (event->xkey.state &
  410.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)));
  411. }
  412.  
  413. static void MoveDino3DBottom(w, event, args, nArgs)
  414.   Dino3DWidget w;
  415.   XEvent *event;
  416.   char *args[];
  417.   int nArgs;
  418. {
  419.   MoveDinoInput((DinoWidget) w, event->xbutton.x, event->xbutton.y, BOTTOM,
  420.     (int) (event->xkey.state & (ShiftMask | LockMask)),
  421.     (int) (event->xkey.state & ControlMask),
  422.     (int) (event->xkey.state &
  423.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)));
  424. }
  425.  
  426. static void MoveDino3DBr(w, event, args, nArgs)
  427.   Dino3DWidget w;
  428.   XEvent *event;
  429.   char *args[];
  430.   int nArgs;
  431. {
  432.   MoveDinoInput((DinoWidget) w, event->xbutton.x, event->xbutton.y, BR,
  433.     (int) (event->xkey.state & (ShiftMask | LockMask)),
  434.     (int) (event->xkey.state & ControlMask),
  435.     (int) (event->xkey.state &
  436.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)));
  437. }
  438.  
  439. static void MoveDino3DCcw(w, event, args, nArgs)
  440.   Dino3DWidget w;
  441.   XEvent *event;
  442.   char *args[];
  443.   int nArgs;
  444. {
  445.   MoveDinoInput((DinoWidget) w, event->xbutton.x, event->xbutton.y, CCW,
  446.     (int) (event->xkey.state & (ShiftMask | LockMask)),
  447.     (int) (event->xkey.state & ControlMask),
  448.     (int) (event->xkey.state &
  449.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)));
  450. }
  451.  
  452. static void ResizePolyhedrons(w)
  453.   Dino3DWidget w;
  454. {
  455.   int face, orient, side, corner;
  456.   XPoint subcubeLoc3D[MAXFACES][MAXORIENT];
  457.   XPoint orientCubeLoc3D[2][MAXFACES][MAXORIENT];
  458.   XPoint subdiamondLoc3D[MAXFACES][MAXORIENT];
  459.   XPoint orientDiamondLoc3D[2][MAXFACES][MAXORIENT];
  460.  
  461.   w->dino.letterOffset.x = -2;
  462.   w->dino.letterOffset.y = 3;
  463.   w->dino3d.viewMiddle.x = w->dino3d.faceSize.x +
  464.     w->dino.puzzleOffset.x;
  465.   w->dino3d.viewMiddle.y = w->dino3d.faceSize.y +
  466.     w->dino.puzzleOffset.y;
  467.   for (face = 0; face < MAXFACES; face++) {
  468.     faceLoc3D[face][0].x = w->dino3d.viewMiddle.x;
  469.     faceLoc3D[face][0].y = w->dino3d.viewMiddle.y;
  470.     for (orient = 1; orient < MAXORIENT; orient++) {
  471.       faceLoc3D[face][orient].x = w->dino3d.faceSize.x;
  472.       faceLoc3D[face][orient].y = w->dino3d.faceSize.y;
  473.     }
  474.   }
  475.   if (w->dino.vertical) {
  476.     faceLoc3D[0][1].x /= -2;
  477.     faceLoc3D[0][1].y /= -1;
  478.     faceLoc3D[0][2].y = 0;
  479.     faceLoc3D[0][3].x /= 2;
  480.  
  481.     faceLoc3D[1][1].x /= -2;
  482.     faceLoc3D[1][2].x /= -2;
  483.     faceLoc3D[1][2].y /= -1;
  484.     faceLoc3D[1][3].x /= 2;
  485.     faceLoc3D[1][3].y /= -1;
  486.  
  487.     faceLoc3D[2][1].y = 0;
  488.     faceLoc3D[2][2].x /= -2;
  489.     faceLoc3D[2][3].x /= -1;
  490.     faceLoc3D[2][3].y = 0;
  491.  
  492.     for (face = MAXFACES / 2; face < MAXFACES; face++)
  493.       faceLoc3D[face][0].y += w->dino3d.viewSize.y + 3;
  494.  
  495.     faceLoc3D[3][1].x /= 2;
  496.     faceLoc3D[3][1].y /= -1;
  497.     faceLoc3D[3][2].x /= 2;
  498.     faceLoc3D[3][3].x /= -2;
  499.  
  500.     faceLoc3D[4][1].x /= -1;
  501.     faceLoc3D[4][1].y = 0;
  502.     faceLoc3D[4][2].x /= 2;
  503.     faceLoc3D[4][2].y /= -1;
  504.     faceLoc3D[4][3].y = 0;
  505.  
  506.     faceLoc3D[5][1].x /= 2;
  507.     faceLoc3D[5][2].x /= -1;
  508.     faceLoc3D[5][2].y = 0;
  509.     faceLoc3D[5][3].x /= -2;
  510.     faceLoc3D[5][3].y /= -1;
  511.   } else {
  512.     faceLoc3D[0][1].x /= -1;
  513.     faceLoc3D[0][1].y /= -2;
  514.     faceLoc3D[0][2].y /= -2;
  515.     faceLoc3D[0][3].y /= 2;
  516.  
  517.     faceLoc3D[1][1].x = 0;
  518.     faceLoc3D[1][2].x /= -1;
  519.     faceLoc3D[1][2].y /= -2;
  520.     faceLoc3D[1][3].x = 0;
  521.     faceLoc3D[1][3].y /= -1;
  522.  
  523.     faceLoc3D[2][1].y /= -2;
  524.     faceLoc3D[2][2].x = 0;
  525.     faceLoc3D[2][3].y /= 2;
  526.     faceLoc3D[2][3].x /= -1;
  527.  
  528.     for (face = MAXFACES / 2; face < MAXFACES; face++)
  529.        faceLoc3D[face][0].x += w->dino3d.viewSize.x + 3;
  530.  
  531.     faceLoc3D[3][1].x /= -1;
  532.     faceLoc3D[3][1].y /= 2;
  533.     faceLoc3D[3][2].x = 0;
  534.     faceLoc3D[3][2].y /= -1;
  535.     faceLoc3D[3][3].y /= -2;
  536.  
  537.     faceLoc3D[4][1].y /= 2;
  538.     faceLoc3D[4][2].x /= -1;
  539.     faceLoc3D[4][2].y /= 2;
  540.     faceLoc3D[4][3].x /= -1;
  541.     faceLoc3D[4][3].y /= -2;
  542.  
  543.     faceLoc3D[5][1].x = 0;
  544.     faceLoc3D[5][1].y /= -1;
  545.     faceLoc3D[5][2].y /= 2;
  546.     faceLoc3D[5][3].x = 0;
  547.   }
  548.  
  549.   for (face = 0; face < MAXFACES; face++) {
  550.     cubeLoc3D[face][0].x = faceLoc3D[face][0].x;
  551.     cubeLoc3D[face][0].y = faceLoc3D[face][0].y;
  552.     subcubeLoc3D[face][0].x = faceLoc3D[face][0].x;
  553.     subcubeLoc3D[face][0].y = faceLoc3D[face][0].y;
  554.     orientCubeLoc3D[0][face][0].x = orientCubeLoc3D[1][face][0].x = 0;
  555.     orientCubeLoc3D[0][face][0].y = orientCubeLoc3D[1][face][0].y = 0;
  556.     for (orient = 1; orient < MAXORIENT; orient++) {
  557.       cubeLoc3D[face][orient].x = faceLoc3D[face][orient].x - 3 *
  558.         w->dino.delta * faceLoc3D[face][orient].x /
  559.         w->dino3d.faceSize.x;
  560.       cubeLoc3D[face][orient].y = faceLoc3D[face][orient].y - 3 *
  561.         w->dino.delta * faceLoc3D[face][orient].y /
  562.         w->dino3d.faceSize.y;
  563.       subcubeLoc3D[face][orient].x = faceLoc3D[face][orient].x -
  564.         4 * faceLoc3D[face][orient].x * w->dino.delta /
  565.         w->dino3d.faceSize.x;
  566.       subcubeLoc3D[face][orient].y = faceLoc3D[face][orient].y -
  567.         4 * faceLoc3D[face][orient].y * w->dino.delta /
  568.         w->dino3d.faceSize.y;
  569.       orientCubeLoc3D[0][face][orient].x = (faceLoc3D[face][orient].x -
  570.         5 * faceLoc3D[face][orient].x * w->dino.delta /
  571.         w->dino3d.faceSize.x) / 3;
  572.       orientCubeLoc3D[0][face][orient].y = (faceLoc3D[face][orient].y -
  573.         5 * faceLoc3D[face][orient].y * w->dino.delta /
  574.         w->dino3d.faceSize.y) / 3;
  575.       orientCubeLoc3D[1][face][orient].x = (faceLoc3D[face][orient].x -
  576.         7 * faceLoc3D[face][orient].x * w->dino.delta /
  577.         w->dino3d.faceSize.x) / 6;
  578.       orientCubeLoc3D[1][face][orient].y = (faceLoc3D[face][orient].y -
  579.         7 * faceLoc3D[face][orient].y * w->dino.delta /
  580.         w->dino3d.faceSize.y) / 6;
  581.     }
  582.  
  583.     MapFrom3D(face, 1, &corner);
  584.     orientTriangle[face][corner][0].x = -orientCubeLoc3D[0][face][2].x / 2;
  585.     orientTriangle[face][corner][0].y = -orientCubeLoc3D[0][face][2].y / 2;
  586.     orientTriangle[face][corner][1].x = -orientCubeLoc3D[1][face][2].x / 2;
  587.     orientTriangle[face][corner][1].y = -orientCubeLoc3D[1][face][2].y / 2;
  588.     for (orient = 0; orient < MAXORIENT - 1; orient++) {
  589.       diamondLoc3D[face][orient].x = (cubeLoc3D[face][orient].x +
  590.         cubeLoc3D[face][orient + 1].x) / 2;
  591.       diamondLoc3D[face][orient].y = (cubeLoc3D[face][orient].y +
  592.         cubeLoc3D[face][orient + 1].y) / 2;
  593.       subdiamondLoc3D[face][orient].x = (subcubeLoc3D[face][orient].x +
  594.         subcubeLoc3D[face][orient + 1].x) / 2;
  595.       subdiamondLoc3D[face][orient].y = (subcubeLoc3D[face][orient].y +
  596.         subcubeLoc3D[face][orient + 1].y) / 2;
  597.       tinyDiamondLoc3D[face][orient + 1].x = diamondLoc3D[face][orient].x -
  598.         subdiamondLoc3D[face][orient].x; 
  599.       tinyDiamondLoc3D[face][orient + 1].y = diamondLoc3D[face][orient].y -
  600.         subdiamondLoc3D[face][orient].y; 
  601.            side = corner;
  602.       orientDiamondLoc3D[0][face][orient].x =
  603.         (orientCubeLoc3D[0][face][orient].x +
  604.         orientCubeLoc3D[0][face][orient + 1].x) / 2;
  605.       orientDiamondLoc3D[0][face][orient].y =
  606.         (orientCubeLoc3D[0][face][orient].y +
  607.         orientCubeLoc3D[0][face][orient + 1].y) / 2;
  608.       orientDiamondLoc3D[1][face][orient].x =
  609.         (orientCubeLoc3D[1][face][orient].x +
  610.         orientCubeLoc3D[1][face][orient + 1].x) / 2;
  611.       orientDiamondLoc3D[1][face][orient].y =
  612.         (orientCubeLoc3D[1][face][orient].y +
  613.         orientCubeLoc3D[1][face][orient + 1].y) / 2;
  614.     }
  615.     /* Its a parallelagram so take advantage of that */
  616.     diamondLoc3D[face][orient].x = (cubeLoc3D[face][MAXORIENT - 1].x -
  617.       cubeLoc3D[face][MAXORIENT / 2].x) / 2;
  618.     diamondLoc3D[face][orient].y = (cubeLoc3D[face][MAXORIENT - 1].y -
  619.       cubeLoc3D[face][MAXORIENT / 2].y) / 2;
  620.     subdiamondLoc3D[face][orient].x = (subcubeLoc3D[face][MAXORIENT - 1].x -
  621.       subcubeLoc3D[face][MAXORIENT / 2].x) / 2;
  622.     subdiamondLoc3D[face][orient].y = (subcubeLoc3D[face][MAXORIENT - 1].y -
  623.       subcubeLoc3D[face][MAXORIENT / 2].y) / 2;
  624.     tinyDiamondLoc3D[face][0].x = diamondLoc3D[face][orient].x -
  625.       subdiamondLoc3D[face][orient].x; 
  626.     tinyDiamondLoc3D[face][0].y = diamondLoc3D[face][orient].y -
  627.       subdiamondLoc3D[face][orient].y; 
  628.     orientDiamondLoc3D[0][face][orient].x =
  629.       (orientCubeLoc3D[0][face][MAXORIENT - 1].x -
  630.       orientCubeLoc3D[0][face][MAXORIENT / 2].x) / 2;
  631.     orientDiamondLoc3D[0][face][orient].y =
  632.       (orientCubeLoc3D[0][face][MAXORIENT - 1].y -
  633.       orientCubeLoc3D[0][face][MAXORIENT / 2].y) / 2;
  634.     orientDiamondLoc3D[1][face][orient].x =
  635.       (orientCubeLoc3D[1][face][MAXORIENT - 1].x -
  636.       orientCubeLoc3D[1][face][MAXORIENT / 2].x) / 2;
  637.     orientDiamondLoc3D[1][face][orient].y =
  638.       (orientCubeLoc3D[1][face][MAXORIENT - 1].y -
  639.       orientCubeLoc3D[1][face][MAXORIENT / 2].y) / 2;
  640.  
  641.     MapFrom3D(face, 1, &corner);
  642.     orientTriangle[face][corner][0].x = -orientCubeLoc3D[0][face][2].x / 2;
  643.     orientTriangle[face][corner][0].y = -orientCubeLoc3D[0][face][2].y / 2;
  644.     orientTriangle[face][corner][1].x = -orientCubeLoc3D[1][face][2].x / 2;
  645.     orientTriangle[face][corner][1].y = -orientCubeLoc3D[1][face][2].y / 2;
  646.  
  647.     triangleLoc3D[face][0][1].x = subdiamondLoc3D[face][2].x;
  648.     triangleLoc3D[face][0][2].x = -subdiamondLoc3D[face][1].x -
  649.       subdiamondLoc3D[face][2].x;
  650.     triangleLoc3D[face][0][1].y = subdiamondLoc3D[face][2].y;
  651.     triangleLoc3D[face][0][2].y = -subdiamondLoc3D[face][1].y -
  652.       subdiamondLoc3D[face][2].y;
  653.     triangleLoc3D[face][1][1].x = -subdiamondLoc3D[face][1].x;
  654.     triangleLoc3D[face][1][2].x = subdiamondLoc3D[face][1].x -
  655.       subdiamondLoc3D[face][2].x;
  656.     triangleLoc3D[face][1][1].y = -subdiamondLoc3D[face][1].y;
  657.     triangleLoc3D[face][1][2].y = subdiamondLoc3D[face][1].y -
  658.       subdiamondLoc3D[face][2].y;
  659.     triangleLoc3D[face][2][1].x = -subdiamondLoc3D[face][2].x;
  660.     triangleLoc3D[face][2][2].x = subdiamondLoc3D[face][1].x +
  661.       subdiamondLoc3D[face][2].x;
  662.     triangleLoc3D[face][2][1].y = -subdiamondLoc3D[face][2].y;
  663.     triangleLoc3D[face][2][2].y = subdiamondLoc3D[face][1].y +
  664.       subdiamondLoc3D[face][2].y;
  665.     triangleLoc3D[face][3][1].x = subdiamondLoc3D[face][1].x;
  666.     triangleLoc3D[face][3][2].x = subdiamondLoc3D[face][2].x -
  667.       subdiamondLoc3D[face][1].x;
  668.     triangleLoc3D[face][3][1].y = subdiamondLoc3D[face][1].y;
  669.     triangleLoc3D[face][3][2].y = subdiamondLoc3D[face][2].y -
  670.       subdiamondLoc3D[face][1].y;
  671.     for (orient = 0; orient < MAXORIENT; orient++) {
  672.       letter3DList[face][orient].x =
  673.         (2 * triangleLoc3D[face][orient][1].x +
  674.          triangleLoc3D[face][orient][2].x) / 3;
  675.       letter3DList[face][orient].y =
  676.         (2 * triangleLoc3D[face][orient][1].y +
  677.          triangleLoc3D[face][orient][2].y) / 3;
  678.       triangleLoc3D[face][orient][3].x =
  679.         -triangleLoc3D[face][orient][1].x - triangleLoc3D[face][orient][2].x;
  680.       triangleLoc3D[face][orient][3].y =
  681.         -triangleLoc3D[face][orient][1].y - triangleLoc3D[face][orient][2].y;
  682.     }
  683.     for (orient = 1; orient < MAXORIENT; orient++) {
  684.       side = corner;
  685.       MapFrom3D(face, (orient + 1) % MAXORIENT, &corner);
  686.       orientTriangle[face][corner][0].x =
  687.         orientTriangle[face][side][0].x +
  688.         orientDiamondLoc3D[0][face][orient].x;
  689.       orientTriangle[face][corner][0].y =
  690.         orientTriangle[face][side][0].y +
  691.         orientDiamondLoc3D[0][face][orient].y;
  692.       orientTriangle[face][corner][1].x =
  693.         orientTriangle[face][side][1].x +
  694.         orientDiamondLoc3D[1][face][orient].x;
  695.       orientTriangle[face][corner][1].y =
  696.         orientTriangle[face][side][1].y +
  697.         orientDiamondLoc3D[1][face][orient].y;
  698.     }
  699.   }
  700.   w->dino3d.cubeSize.x = w->dino3d.faceSize.x - 2 * w->dino.delta;
  701.   w->dino3d.cubeSize.y = w->dino3d.faceSize.y - 2 * w->dino.delta;
  702.   w->dino3d.cubeDiagonal = w->dino3d.faceDiagonal - 2 * w->dino.delta;
  703.   w->dino3d.cubeDiag = w->dino3d.faceDiagonal + 2 * w->dino.delta;
  704. }
  705.  
  706. int SelectPolyhedrons3D(w, x, y, face, position)
  707.   Dino3DWidget w;
  708.   int x, y;
  709.   int *face, *position;
  710. {
  711.   int u, v, front, tl, ur, ul, found, corner, x1, y1, x2, y2, dx, dy;
  712.  
  713.   x1 = x;
  714.   y1 = y;
  715.   if (w->dino.vertical) {
  716.     x -= w->dino3d.viewMiddle.x;
  717.     front = (y < w->dino3d.viewSize.y);
  718.     if (!front)
  719.       y -= (w->dino3d.viewSize.y);
  720.     tl = (y < w->dino3d.viewMiddle.y);
  721.     y -= w->dino3d.viewMiddle.y;
  722.     u = -w->dino3d.faceSize.y * x + w->dino3d.faceDiagonal * y;
  723.     v = w->dino3d.faceSize.y * x + w->dino3d.faceDiagonal * y;
  724.     ur = (u < 0);
  725.     ul = (v < 0);
  726.     if (front) {
  727.       if (tl)
  728.         *face = (ur) ? 0 : 1;
  729.       else
  730.         *face = (ul) ? 1 : 2;
  731.     } else {
  732.       if (tl)
  733.         *face = (ul) ? 4 : 3;
  734.       else
  735.         *face = (ur) ? 3 : 5;
  736.     }
  737.   } else {
  738.     y -= w->dino3d.viewMiddle.y;
  739.     front = (x < w->dino3d.viewSize.x);
  740.     if (!front)
  741.       x -= (w->dino3d.viewSize.x);
  742.     tl = (x < w->dino3d.viewMiddle.x);
  743.     x -= w->dino3d.viewMiddle.x;
  744.     u = -w->dino3d.faceSize.x * y + w->dino3d.faceDiagonal * x;
  745.     v = w->dino3d.faceSize.x * y + w->dino3d.faceDiagonal * x;
  746.     ur = (u < 0);
  747.     ul = (v < 0);
  748.     if (front) {
  749.       if (tl)
  750.         *face = (ur) ? 1 : 0;
  751.       else
  752.         *face = (ul) ? 0 : 2;
  753.     } else {
  754.       if (tl)
  755.         *face = (ul) ? 3 : 4;
  756.       else
  757.         *face = (ur) ? 4 : 5;
  758.     }
  759.   }
  760.   x = x1;
  761.   y = y1;
  762.   found = 0;
  763.   DiamondOffset3D(w, *face, &dx, &dy);
  764.   for (corner = 0; corner < MAXORIENT; corner++) {
  765.     int ok = 0;
  766.  
  767.     x1 = dx + triangleLoc3D[*face][corner][1].x;
  768.     y1 = dy + triangleLoc3D[*face][corner][1].y;
  769.     x2 = x1 + triangleLoc3D[*face][corner][2].x;
  770.     y2 = y1 + triangleLoc3D[*face][corner][2].y;
  771.     if ((x1 - dx) * (y2 - dy) <= (y1 - dy) * (x2 - dx)) {
  772.       if ((x1 - dx) * (y - dy) <= (y1 - dy) * (x - dx))
  773.         ok++;
  774.     } else if ((x1 - dx) * (y - dy) >= (y1 - dy) * (x - dx))
  775.       ok++;
  776.     if ((x2 - dx) * (y1 - dy) <= (y2 - dy) * (x1 - dx)) {
  777.       if ((x2 - dx) * (y - dy) <= (y2 - dy) * (x - dx))
  778.         ok++;
  779.     } else if ((x2 - dx) * (y - dy) >= (y2 - dy) * (x - dx))
  780.       ok++;
  781.     if (ok == 2) {
  782.       MapFrom3D(*face, corner, position);
  783.       found++;
  784.     }
  785.   }
  786.   if (found != 1)
  787.     return FALSE;
  788.   return TRUE;
  789. }
  790.  
  791.  
  792. int NarrowSelection3D(w, face, direction)
  793.   Dino3DWidget w;
  794.   int *face;
  795.   int *direction;
  796. {
  797.   switch (*direction) {
  798.     case TR:
  799.     case BR:
  800.     case BL:
  801.     case TL:
  802.       if (w->dino.vertical) {
  803.         if (*face == 1)
  804.           *direction = *direction + 2 * MAXORIENT;
  805.         else if (*face == 3)
  806.           *direction = (*direction + 3) % MAXORIENT + 2 * MAXORIENT;
  807.       } else {
  808.         if (*face == 0)
  809.           *direction = (*direction + 3) % MAXORIENT + 2 * MAXORIENT;
  810.         else if (*face == 4)
  811.           *direction = (*direction + 2) % MAXORIENT + 2 * MAXORIENT;
  812.         if (*face == 5)
  813.           *direction = (*direction + 2) % MAXORIENT;
  814.       }
  815.       break;
  816.     case CCW:
  817.     case CW:
  818.       if (*face == 3 || *face == 4)
  819.         *direction = (TR + *direction - CW) % MAXORIENT;
  820.       else if (*face == 0)
  821.         *direction = (BR + *direction - CW) % MAXORIENT;
  822.       else if (*face == 2)
  823.         *direction = (BL + *direction - CW) % MAXORIENT;
  824.       else if (*face == 1 || *face == 5)
  825.         *direction = (TL + *direction - CW) % MAXORIENT;
  826.       break;
  827.     case TOP:
  828.     case RIGHT:
  829.     case BOTTOM:
  830.     case LEFT:
  831.       if (w->dino.vertical) {
  832.         if (*face == 1)
  833.           *direction = (TL + *direction) % MAXORIENT;
  834.         else if (*face == 3)
  835.           *direction = (BL + *direction) % MAXORIENT;
  836.       } else {
  837.         if (*face == 0)
  838.           *direction = (TR + *direction) % MAXORIENT;
  839.         else if (*face == 4)
  840.           *direction = (BR + *direction) % MAXORIENT;
  841.         else if (*face == 5)
  842.           *direction = (BL + *direction) % MAXORIENT + 2 * MAXORIENT;
  843.       }
  844.       break;
  845.     default:
  846.       return FALSE;
  847.   }
  848.   return TRUE;
  849. }
  850.  
  851. static void DrawFrame(w, gc)
  852.   Dino3DWidget w;
  853.   GC gc;
  854. {
  855.   int face, dx, dy;
  856.  
  857.   dx = w->dino3d.viewSize.x + w->dino.puzzleOffset.x;
  858.   dy = w->dino3d.viewSize.y + w->dino.puzzleOffset.y;
  859.   if (w->dino.vertical) {
  860.     XDrawLine(XtDisplay(w), XtWindow(w), gc,
  861.       0, dy, dx + w->dino.puzzleOffset.x + 1, dy);
  862.     XDrawString(XtDisplay(w), XtWindow(w), gc,
  863.       (int) (2 * w->dino.delta),
  864.       (int) (3 * w->dino.delta + w->dino.letterOffset.y),
  865.       "Front", 5);
  866.     XDrawString(XtDisplay(w), XtWindow(w), gc, (int)
  867.       (-4 * w->dino.delta + 2 * 4 * w->dino.letterOffset.x + w->core.width), 
  868.       (int) (-w->dino.delta - 2 * w->dino.letterOffset.y + w->core.height),
  869.       "Back", 4);
  870.   } else {
  871.     XDrawLine(XtDisplay(w), XtWindow(w), gc,
  872.       dx, 0, dx, dy + w->dino.puzzleOffset.y + 1);
  873.     XDrawString(XtDisplay(w), XtWindow(w), gc,
  874.       (int) (2 * w->dino.delta),
  875.       (int) (3 * w->dino.delta + w->dino.letterOffset.y),
  876.       "Front", 5);
  877.     XDrawString(XtDisplay(w), XtWindow(w), gc, (int)
  878.       (-4 * w->dino.delta + 2 * 4 * w->dino.letterOffset.x + w->core.width), 
  879.       (int) (-w->dino.delta - 2 * w->dino.letterOffset.y + w->core.height),
  880.       "Back", 4);
  881.   }
  882.   for (face = 0; face < MAXFACES; face++)
  883.     XDrawLines(XtDisplay(w), XtWindow(w), gc,
  884.       faceLoc3D[face], MAXORIENT, CoordModePrevious);
  885. }   
  886.  
  887. void DrawTriangle3D(w, face, position, offset)
  888.   Dino3DWidget w;
  889.   int face, position, offset;
  890. {
  891.   int corner, dx, dy, letterX, letterY;
  892.  
  893.   MapTo3D(face, position, &corner);
  894.   CubeOffset3D(w, face, corner, &dx, &dy);
  895.   letterX = dx + letter3DList[face][corner].x;
  896.   letterY = dy + letter3DList[face][corner].y;
  897.   triangleLoc3D[face][corner][0].x = dx;
  898.   triangleLoc3D[face][corner][0].y = dy;
  899.   if (offset) {
  900.     XFillPolygon(XtDisplay(w), XtWindow(w),
  901.       w->dino.borderGC,
  902.       triangleLoc3D[face][corner], 3, Convex, CoordModePrevious);
  903.     XDrawLines(XtDisplay(w), XtWindow(w),
  904.       w->dino.faceGC[w->dino.cubeLoc[face][position].face],
  905.       triangleLoc3D[face][corner], 4, CoordModePrevious);
  906.   } else {
  907.     XFillPolygon(XtDisplay(w), XtWindow(w),
  908.       w->dino.faceGC[w->dino.cubeLoc[face][position].face],
  909.       triangleLoc3D[face][corner], 3, Convex, CoordModePrevious);
  910.     XDrawLines(XtDisplay(w), XtWindow(w),
  911.       w->dino.borderGC, triangleLoc3D[face][corner], 4, CoordModePrevious);
  912.   }
  913.   if (w->dino.depth == 1 || w->dino.mono) {
  914.     char buf[2];
  915.  
  916.     (void) sprintf (buf, "%c",
  917.       w->dino.faceName[w->dino.cubeLoc[face][position].face][0]);
  918.     XDrawString(XtDisplay(w), XtWindow(w), w->dino.inverseGC,
  919.       letterX + w->dino.letterOffset.x, letterY + w->dino.letterOffset.y,
  920.       buf, 1);
  921.   }
  922.   if (w->dino.orient)
  923.     XDrawLine(XtDisplay(w), XtWindow(w), w->dino.inverseGC,
  924.       letterX +
  925.         orientTriangle[face][w->dino.cubeLoc[face][position].rotation][0].x,
  926.       letterY +
  927.         orientTriangle[face][w->dino.cubeLoc[face][position].rotation][0].y,
  928.       letterX +
  929.         orientTriangle[face][w->dino.cubeLoc[face][position].rotation][1].x,
  930.       letterY +
  931.         orientTriangle[face][w->dino.cubeLoc[face][position].rotation][1].y);
  932. }
  933.  
  934. static void MapTo3D(face, corner, side)
  935.   int face, corner, *side;
  936. {
  937.   switch (face) {
  938.     case 0:
  939.       *side = (corner + 2) % MAXORIENT;
  940.       break;
  941.     case 1:
  942.     case 5:
  943.       *side = corner;
  944.       break;
  945.     case 2:
  946.       *side = (corner + 1) % MAXORIENT;
  947.       break;
  948.     case 3:
  949.     case 4:
  950.       *side = (corner + 3) % MAXORIENT;
  951.       break;
  952.     default:
  953.       (void) printf ("MapTo3D: face %d\n", face);
  954.   }
  955. }
  956.  
  957. static void MapFrom3D(face, side, corner)
  958.   int face, side, *corner;
  959. {
  960.   switch (face) {
  961.     case 0:
  962.       *corner = (side + 2) % MAXORIENT;
  963.       break;
  964.     case 1:
  965.     case 5:
  966.       *corner = side;
  967.       break;
  968.     case 2:
  969.       *corner = (side + 3) % MAXORIENT;
  970.       break;
  971.     case 3:
  972.     case 4:
  973.       *corner = (side + 1) % MAXORIENT;
  974.       break;
  975.     default:
  976.       (void) printf ("MapFrom3D: face %d\n", face);
  977.   }
  978. }
  979.  
  980. static void DiamondOffset3D(w, face, dx, dy)
  981.   Dino3DWidget w;
  982.   int face, *dx, *dy;
  983. {
  984.   if (w->dino.vertical) {
  985.     switch (face) {
  986.       case 0:
  987.         *dx = (2 * faceLoc3D[0][0].x + faceLoc3D[0][1].x +
  988.                faceLoc3D[0][2].x) / 2;
  989.         *dy = (2 * faceLoc3D[0][0].y + faceLoc3D[0][1].y) / 2;
  990.         break;
  991.       case 1:
  992.         *dx = faceLoc3D[1][0].x + faceLoc3D[1][1].x;
  993.         *dy = faceLoc3D[1][0].y;
  994.         break;
  995.       case 2:
  996.         *dx = (2 * faceLoc3D[2][0].x + faceLoc3D[2][1].x +
  997.                faceLoc3D[2][2].x) / 2;
  998.         *dy = (2 * faceLoc3D[2][0].y + faceLoc3D[2][1].y +
  999.                faceLoc3D[2][2].y) / 2;
  1000.         break;
  1001.       case 3:
  1002.         *dx = faceLoc3D[3][0].x + faceLoc3D[3][1].x;
  1003.         *dy = faceLoc3D[3][0].y;
  1004.         break;
  1005.       case 4:
  1006.         *dx = (2 * faceLoc3D[4][0].x + faceLoc3D[4][1].x +
  1007.                faceLoc3D[4][2].x) / 2;
  1008.         *dy = (2 * faceLoc3D[4][0].y + faceLoc3D[4][1].y +
  1009.                faceLoc3D[4][2].y) / 2;
  1010.         break;
  1011.       case 5:
  1012.         *dx = (2 * faceLoc3D[5][0].x + faceLoc3D[5][1].x +
  1013.                faceLoc3D[5][2].x) / 2;
  1014.         *dy = (2 * faceLoc3D[5][0].y + faceLoc3D[5][1].y) / 2;
  1015.         break;
  1016.       default:
  1017.         (void) printf ("DiamondOffset3D: face %d\n", face);
  1018.     }
  1019.   }
  1020.   else
  1021.   {
  1022.     switch (face)
  1023.     {
  1024.       case 0:
  1025.         *dx = faceLoc3D[0][0].x;
  1026.         *dy = faceLoc3D[0][0].y + faceLoc3D[0][1].y;
  1027.         break;
  1028.       case 1:
  1029.         *dx = (2 * faceLoc3D[1][0].x + faceLoc3D[1][1].x +
  1030.                faceLoc3D[1][2].x) / 2;
  1031.         *dy = (2 * faceLoc3D[1][0].y + faceLoc3D[1][1].y +
  1032.                faceLoc3D[1][2].y) / 2;
  1033.         break;
  1034.       case 2:
  1035.         *dx = (2 * faceLoc3D[2][0].x + faceLoc3D[2][1].x) / 2;
  1036.         *dy = (2 * faceLoc3D[2][0].y + faceLoc3D[2][1].y +
  1037.                faceLoc3D[2][2].y) / 2;
  1038.         break;
  1039.       case 3:
  1040.         *dx = (2 * faceLoc3D[3][0].x + faceLoc3D[3][1].x) / 2;
  1041.         *dy = (2 * faceLoc3D[3][0].y + faceLoc3D[3][1].y +
  1042.                faceLoc3D[3][2].y) / 2;
  1043.         break;
  1044.       case 4:
  1045.         *dx = faceLoc3D[4][0].x;
  1046.         *dy = faceLoc3D[4][0].y + faceLoc3D[4][1].y;
  1047.         break;
  1048.       case 5:
  1049.         *dx = (2 * faceLoc3D[5][0].x + faceLoc3D[5][1].x +
  1050.                faceLoc3D[5][2].x) / 2;
  1051.         *dy = (2 * faceLoc3D[5][0].y + faceLoc3D[5][1].y +
  1052.                faceLoc3D[5][2].y) / 2;
  1053.         break;
  1054.       default:
  1055.         (void) printf ("DiamondOffset3D: face %d\n", face);
  1056.     }
  1057.   }
  1058. }
  1059.  
  1060. static void CubeOffset3D(w, face, side, dx, dy)
  1061.   Dino3DWidget w;
  1062.   int face, side, *dx, *dy;
  1063. {
  1064.   int corner;
  1065.  
  1066.   DiamondOffset3D(w, face, dx, dy);
  1067.   for (corner = 1; corner <= side; corner++)
  1068.   {
  1069.     *dx += tinyDiamondLoc3D[face][corner].x;
  1070.     *dy += tinyDiamondLoc3D[face][corner].y;
  1071.   }
  1072. }
  1073.